package com.jieshuibao.util;

import java.security.Security;











import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.jieshuibao.common.utils.Md5Util;
import com.jieshuibao.wx.util.PayCommonUtil;



/*import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;*/

/**
 * aes加密 兼容linux/windows
 * 
 * @author MrZhang
 *
 */
public class AesUtil {
	
	 /** 
     * 密钥算法 
     */  
    private static final String ALGORITHM = "AES";  
    /** 
     * 加解密算法/工作模式/填充方式 
     */  
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";  
    /** 
     * 生成key 
     */  
    private static SecretKeySpec key = new SecretKeySpec(Md5Util.Md5(PayCommonUtil.API_KEY).toLowerCase().getBytes(), ALGORITHM);  
    public static boolean initialized = false;  

   // public static final String ALGORITHM = "AES/ECB/PKCS7Padding";  

	//public static void main(String[] args) {

//		String content = "test";
//		String password = "12345678";
//		byte[] encryptResult = encrypt(content, password);// 加密

		/* 容易出错的地方，请看下面代码 */
		// try {
		// String encryptResultStr = new String(encryptResult,"utf-8");
		// decryptResult = decrypt(encryptResultStr.getBytes("utf-8"),password);
		// } catch (UnsupportedEncodingException e) {
		// e.printStackTrace();
		// } catch (Exception e) {
		// // TODO: handle exception
		// }
		/*
		 * 则，系统会报出如下异常：javax.crypto.IllegalBlockSizeException: Input length must
		 * be multiple of 16 when decrypting with padded cipher at
		 * com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at
		 * com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at
		 * com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) at
		 * javax.crypto.Cipher.doFinal(DashoA13*..) at
		 * cn.com.songjy.test.ASCHelper.decrypt(ASCHelper.java:131) at
		 * cn.com.songjy.test.ASCHelper.main(ASCHelper.java:58)
		 */
		/*
		 * 这主要是因为加密后的byte数组是不能强制转换成字符串的, 换言之,字符串和byte数组在这种情况下不是互逆的,
		 * 要避免这种情况，我们需要做一些修订，可以考虑将二进制数据转换成十六进制表示,
		 * 主要有两个方法:将二进制转换成16进制(见方法parseByte2HexStr
		 * )或是将16进制转换为二进制(见方法parseHexStr2Byte)
		 */

		/* 然后，我们再修订以上测试代码 */
//		String encryptResultStr = parseByte2HexStr(encryptResult);
//
//		byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);
//		byte[] decryptResult = decrypt(decryptFrom, password);// 解码
	//}

	/**
	 * 加密
	 * 
	 * @method encrypt
	 * @param content
	 *            需要加密的内容
	 * @param password
	 *            加密密码
	 * @return
	 * @throws
	 * @since v1.0
	 */
	/*public static byte[] encrypt(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			*//**
			 * SecureRandom 实现完全随操作系统本身的內部状态，除非调用方在调用 getInstance 方法之后又调用了
			 * setSeed 方法； 该实现在 windows 上每次生成的 key 都相同，但是在 solaris 或部分 linux
			 * 系统上则不同。
			 *//*
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(password.getBytes());
			kgen.init(128, secureRandom);

			// kgen.init(128, new
			// SecureRandom(password.getBytes()));//windows上直接用就可以
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	*//**
	 * 解密
	 * 
	 * @method decrypt
	 * @param content
	 *            待解密内容
	 * @param password
	 *            解密密钥
	 * @return
	 * @throws
	 * @since v1.0
	 *//*
	public static byte[] decrypt(byte[] content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(password.getBytes());
			kgen.init(128, secureRandom);
			// kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(content);
			return result; // 解密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}

		return null;
	}

	*//**
	 * 将二进制转换成16进制
	 * 
	 * @method parseByte2HexStr
	 * @param buf
	 * @return
	 * @throws
	 * @since v1.0
	 *//*
	public static String parseByte2HexStr(byte buf[]) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			sb.append(hex.toUpperCase());
		}
		return sb.toString();
	}

	*//**
	 * 将16进制转换为二进制
	 * 
	 * @method parseHexStr2Byte
	 * @param hexStr
	 * @return
	 * @throws
	 * @since v1.0
	 *//*
	public static byte[] parseHexStr2Byte(String hexStr) {
		if (hexStr.length() < 1)
			return null;
		byte[] result = new byte[hexStr.length() / 2];
		for (int i = 0; i < hexStr.length() / 2; i++) {
			int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
					16);
			result[i] = (byte) (high * 16 + low);
		}
		return result;
	}

	/**
	 * 另外一种加密方式--这种加密方式有两种限制 1、密钥必须是16位的 2、待加密内容的长度必须是16的倍数，如果不是16的倍数，就会出如下异常
	 * javax.crypto.IllegalBlockSizeException: Input length not multiple of 16
	 * bytes at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..) at
	 * com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at
	 * com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at
	 * com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) at
	 * javax.crypto.Cipher.doFinal(DashoA13*..) 要解决如上异常，可以通过补全传入加密内容等方式进行避免。
	 * 
	 * @method encrypt2
	 * @param content
	 *            需要加密的内容
	 * @param password
	 *            加密密码
	 * @return
	 * @throws
	 * @since v1.0
	 */
/*	public static byte[] encrypt2(String content, String password) {
		try {
			SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
			Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}*/
	
	/**
	 * 可以看到，代码开头要先import Java Cryptography Extension (JCE)中的两个类——加/解密类Cipher和密钥类SecretKeySpec，
	 * 以及BouncyCastle的一个开源加/解密类库中的加/解密算法提供者类BouncyCastleProvider。
		PC上的Java里面只有"AES/ECB/PKCS5Padding"算法，没有"AES/ECB/PKCS7Padding"算法。故需要引入BouncyCastle的库，
		并给Cipher.getInstance方法传入参数"BC"来指定Java使用这个库里的加/解密算法。BouncyCastle的加/解密类库的下载地址：
		http://www.bouncycastle.org/latest_releases.html在这段代码可以运行之前，还有一个问题需要解决。
		Java本身限制密钥的长度最多128位，而AES256需要的密钥长度是256位，因此需要到Java官网上下载一个
		Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。
		在Java SE的下载页面下面的Additional Resources那里会有下载链接。下载后打开压缩包，里面有两个jar文件。
		把这两个jar文件解压到JRE目录下的lib/security文件夹，覆盖原来的文件。这样Java就不再限制密钥的长度了。
	 */
	
	 /** 
     * AES加密 
     *  
     * @param data 
     * @return 
     * @throws Exception 
     */  
    public static String encryptData(String data) throws Exception { 
    	   Security.addProvider(new BouncyCastleProvider());  
    	 //Cipher cipher = Cipher.getInstance(ALGORITHM, "ECB");
        // 创建密码器  
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);  
        // 初始化  
        cipher.init(Cipher.ENCRYPT_MODE, key);  
        return Base64Util.encode(cipher.doFinal(data.getBytes()));  
    }  
  
    /** 
     * AES解密 
     *  
     * @param base64Data 
     * @return 
     * @throws Exception 
     */  
    public static String decryptData(String base64Data) throws Exception { 
    	   Security.addProvider(new BouncyCastleProvider());  
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);  
        cipher.init(Cipher.DECRYPT_MODE, key);  
        return new String(cipher.doFinal(Base64Util.decode(base64Data)));  
    }  
  /**
   * 请求参数解密
   * @param base64Data
   * @return
   * @throws Exception
   */
    public static String rquestDecryData(String base64Data ,String key)throws Exception{
    	SecretKeySpec requestKey = new SecretKeySpec(key.getBytes(), ALGORITHM); 
    	 
    	   Security.addProvider(new BouncyCastleProvider());  
           Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
           IvParameterSpec ivParameterSpec = new IvParameterSpec("JlBUliXUELogBing".getBytes());
           cipher.init(Cipher.DECRYPT_MODE, requestKey,ivParameterSpec);  
           return new String(cipher.doFinal(Base64Util.decode(base64Data)));  
    	
    }
    /**
     * 请求参数加密
     * @param data
     * @return
     * @throws Exception
     */
    public static String rquestencryptData(String data,String key)throws Exception{
    	SecretKeySpec requestKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
    	   Security.addProvider(new BouncyCastleProvider());  
      	 //Cipher cipher = Cipher.getInstance(ALGORITHM, "ECB");
          // 创建密码器  
          Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");  
          // 初始化  
          IvParameterSpec ivParameterSpec = new IvParameterSpec("JlBUliXUELogBing".getBytes());
          cipher.init(Cipher.ENCRYPT_MODE, requestKey,ivParameterSpec);  
          return Base64Util.encode(cipher.doFinal(data.getBytes()));  
    	
    }
    public static void main(String[] args) throws Exception { 
    	//key = new SecretKeySpec(Md5Util.Md5("dsfdfdsfsdfsdfs").toLowerCase().getBytes(), ALGORITHM);  
    	String encryptData = encryptData("liuxuebing");
    	
    	String rquestencryptData = rquestencryptData("71e56a922f864bb6a0755971b3c144bb","71e56a922f864bb6a0755971b3c144bb");
    	
    	System.out.println("密文1："+encryptData);
    	System.out.println("密文2："+rquestencryptData);
    	String decryptData = decryptData(encryptData);
    	String rquestDecryData = rquestDecryData(rquestencryptData,"71e56a922f864bb6a0755971b3c144bb");
    	System.out.println("明文1："+decryptData);
    	System.out.println("明文2："+rquestDecryData);
    	//测试微信加密解密
    /*	String req_info="Tm/SYkcgMyqQb+vFm+ocpLrwMYTEvMKJIC6i1uij5VS4v2kIoEzfjvmoOfNMGjlXRUa1l4uSasyRcogDI+Nwx3+hx2wAL1C7YgvVF45YB4VYJxR+EaHUowd4naYO3ko8CuAmVZqtmiTaWX3HyJgPBTcRmaybiJm2yDdXyAbVn5wRpnvoOTcQWRgP18yh4zqkY3+mKuuxTCx1sKFu2W17ZYQw8HvrAhXFBQdHsUKY26/5l3VjAPmnhSykH+zlegIu3i8qpHeNXpfby4dUjMzLTPHIbIazZ3ghok4/d1/wkGCN9TujSK4heXT/NFropUNP5gItr2skYV8XvW+xUfO6aBmCIrbWOwKifsk13KcgPeou1DAJlhlYSH8WQr3EIrIZjUMeMMq5skalNkXVFdhso3UnSMYBytowHbSJoQbHqkX5E90PmjGJSmma1C9Kcwv3F3Tr4QzeEK6QDA4TUPT2rl3u9J60a/kpMfrtOkfvBFRBSVuqbseCMAXqJaCn2bqF2Iqf1MfOr0KaXcvQ2FVGkZZuicm64qj9Nlp82K7IYp1M5L4uxbOP9aCu1fbGjj2uv//mD2cqno+kLlGAHgyQyou+kZgmK4nnW8GRRxeTLY4/TY4/Kx3cmCSAJQZYpQsf/AfOeyygYLa7wjuVZDmPq+R9tiXDUewuREFuVw/ug8dUOnndvxGBXhbGfdBSTYiyrt2o+s5g9gBab0ut1Bo2DhowgaGHQHfmuVbBQRAwtDfaNNC9yxj4lledioB10cALCSZGWuzp7Zc0+Y1S7ZiJPVkvsoDm9QGZ+oOxorOqSHS9xip/VdjH3FFJmucIEPEyJ9LWk/hZ26Ps0jY5voNQOWDuBUxe4DFn6ZL8kJu5DY+fyMH14k7SQuXJIMujSxZg7woqvJbTkBNGAI+vDeBbgeFJR76p2fk8zr3No1FixTpKPciRJ8RfptEGwsXK40p2ylaXAIODmr63StA0OU0n2qFhl42UGq6BeAGho3pT4nhbqFsZHtAv1TlKGcIPFSdj8EWz/8O2hOWqp0mSWqFw4w==";

        String B = AesUtil.decryptData(req_info);  
        System.out.println("解密"+B);
        
        Map<String, String> xmlToMap = PayCommonUtil.xmlToMap(B);
        System.out.println(xmlToMap.get("settlement_refund_fee"));
        System.out.println(JsonUtil.toJson(xmlToMap));
               
        //加密
        String str = "<root>"+
                "<out_refund_no><![CDATA[2531340110812300]]></out_refund_no>"+
                "<out_trade_no><![CDATA[2531340110812100]]></out_trade_no>"+
                "<refund_account><![CDATA[REFUND_SOURCE_RECHARGE_FUNDS]]></refund_account>"+
                "<refund_fee><![CDATA[1]]></refund_fee>"+
                "<refund_id><![CDATA[50000505542018011003064518841]]></refund_id>"+
                "<refund_recv_accout><![CDATA[支付用户零钱]]></refund_recv_accout>"+
                "<refund_request_source><![CDATA[API]]></refund_request_source>"+
                "<refund_status><![CDATA[SUCCESS]]></refund_status>"+
                "<settlement_refund_fee><![CDATA[1]]></settlement_refund_fee>"+
                "<settlement_total_fee><![CDATA[1]]></settlement_total_fee>"+
                "<success_time><![CDATA[2018-01-10 10:31:24]]></success_time>"+
                "<total_fee><![CDATA[1]]></total_fee>"+
                "<transaction_id><![CDATA[4200000052201801101409025381]]></transaction_id>"+
                "</root>";
        System.out.println("加密"+encryptData(str));*/
    	
    	
    }  

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   /* *//** 
     * @param  String str  要被加密的字符串 
     * @param  byte[] key  加/解密要用的长度为32的字节数组（256位）密钥 
     * @return byte[]  加密后的字节数组 
     *//*  
    public static byte[] Aes256Encode(String str, byte[] key){  
        initialize();  
        byte[] result = null;  
        try{  
            Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");  
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); //生成加密解密需要的Key  
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);  
            result = cipher.doFinal(str.getBytes("UTF-8"));  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
        return result;  
    }  
      
    *//** 
     * @param  byte[] bytes  要被解密的字节数组 
     * @param  byte[] key    加/解密要用的长度为32的字节数组（256位）密钥 
     * @return String  解密后的字符串 
     *//*  
    public static String Aes256Decode(byte[] bytes, byte[] key){  
        initialize();  
        String result = null;  
        try{  
            Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");  
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); //生成加密解密需要的Key  
            cipher.init(Cipher.DECRYPT_MODE, keySpec);  
            byte[] decoded = cipher.doFinal(bytes);  
            result = new String(decoded, "UTF-8");  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
        return result;  
    }  
      
    public static void initialize(){  
        if (initialized) return;  
        Security.addProvider(new BouncyCastleProvider());  
        initialized = true;  
    }  
    
    public static void main(String[] args) {
      String req_info="Ih5osM/5IbPfHouVrUmwebd1yAW2Gys91jv006W1237sSi3z022KxHafLIDMrQLYiBttTadgvy2cbx6DnmwDIQ52lPWfo6pAAHt7Q9DjBIpDRQ7JsbEBlomoQP2ZkdNHnWscVYuFEVlItaSlkSlcKLdB4UwMduqDYseFsUUthz6htPeBu987zXS6dKrgIbRwOxt5RfPmk1sf0oVB2yU3UH0Ly8SzBjmN1jrh4qAaUkfH6VkeMJcsZSGchQn2VresxJTbGH++JE1UsXUF3gyYpweyxBPtHoKdaggsIONR20UKNxJYPJLnEOnfQF/Ipmk8/QmTVRK7iqfVLC9EA1Auma0AlKBjZlYqynUlF3y+E2ZzgWMUlvDHZVWDbzp/TcE0q+Ukc7yQ3HBsibDR474SPlLTkCWz1iydXzkVcLqJKamsh76Liv1a0hzu0sI3qasMAfmwU6/q7/N6quq031toO1GxqkVaxBRK7e64gSOx9ArxxVFgZ7WN+JPq2OH/pTKH8ToxHA0rtxN5+aAgZGkXiIOUiHtp4mjpRxqe34WK7C7Nr0DQyOVwsXT2TTegSgWGm34aa//ZYxHedubv2iX+E7K222lptg9IqHlMXBbwKFtKtIcal61+8ciz+sB1FBpqHchC+3whTqWv5ZANiHBzaOhbIbA/mKX2XZ6Cy0iYh+bL/8Y/Hvz/UnMGzor+2anIUeBAGRQmseL4jY+Qic46WLuEhDcarCaO4JgJSAOC+VmsdrER9TRum26PFwTQwtNpxkrKCiO9Gv36Ood5D8hXnLHUH+4nbsek8ouxkCcFXq4Us0mipB3i5ksQpt23LiJm9Ahxyvptp9Q41SytS48NXiz3IxTOqDdknowedZwAtJ/fhBlwiOHD9N+pECXuNBKLaCZcatGycr0/DPELiCF+MIRQ6V60wzaZD74TKRFULd1ljNsoQIAbuGaT40WMDY6a28jBHQ/IXnD4gvSvfeumwQzp3Q9PiPyFtF6JxH7RBRj9/lmQuQozJIPZCaCNVTBfWQOdcFaBnPLN0ZNvzjA93g6jcIxHzkXHmiGfh98vq2E=";
      byte[] bytes = Md5Util.Md5("2IBtBXdrqC3kCBs4gaceL7nl2nnFadQv").toLowerCase().getBytes();
      byte[] aes256Encode = Aes256Encode(req_info, bytes);
      System.out.println(aes256Encode);
      
      try {
		String string = new String(aes256Encode, "UTF-8");
		
		System.out.println("========"+string);
		
		String aes256Decode = Aes256Decode(aes256Encode, bytes);
		System.out.println(aes256Decode);
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	}
	}*/
}
